package com.pz.minioproxy.service;

import com.alibaba.druid.util.StringUtils;
import com.pz.gulimall.common.exception.RRException;
import com.pz.minioproxy.config.MinioConfig;
import com.pz.minioproxy.constant.MinioCodeEnum;
import io.minio.GetPresignedObjectUrlArgs;
import io.minio.MinioClient;
import io.minio.PutObjectArgs;
import io.minio.http.Method;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.io.FileUtils;
import org.apache.commons.io.IOUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;

import java.io.*;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.UUID;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;

@Service
@Slf4j
public class UploadFileService {
    @Autowired
    private MinioClient minioClient;
    @Autowired
    private MinioConfig minioConfig;
    @Autowired
    private ThreadPoolExecutor executor;

    //以时间作为文件夹
    private static final SimpleDateFormat sdf = new SimpleDateFormat("yyyy/MM/dd/");

    /**
     * 文件上传服务本地
     * @param zipFile 上传文件流
     * @param path 存储在本服务器的路径
     * @param fileName 文件名称
     * */
    public void upLoadFileToLocal(MultipartFile zipFile, String path, String fileName) {
        if(zipFile.isEmpty()){
            throw new RRException("uploadFile empty");
        }
        File targetFile = new File(path,fileName);
        try {
            FileUtils.forceMkdir(new File(path));
        } catch (IOException e) {
            log.error(e.getMessage());
            throw new RRException("makeDir:"+path+" fail!!!");
        }
        FileOutputStream fileOutputStream = null;
        try {
            fileOutputStream = new FileOutputStream(targetFile);
            IOUtils.copy(zipFile.getInputStream(),fileOutputStream);
        } catch (IOException e) {
            log.error(e.getMessage());
            throw new RRException("IO write/read fail");
        }finally {
            if(fileOutputStream!=null){
                try {
                    fileOutputStream.close();
                } catch (IOException e) {
                    log.error("close stream fail!!",e);
                }
            }
        }
        log.info("uploadFile-{},success!",fileName);
    }

    /**
     * 上传文件，返回存储名
     * @param file 上传文件
     * @return bucket,objectName
     */
    public String uploadFile(MultipartFile file) throws RuntimeException {
        log.debug("Type of upload file is {}", file.getContentType());
        InputStream inputStream;
        try {
            inputStream = file.getInputStream();
        } catch (IOException e) {
            throw new RRException(e.getMessage(), MinioCodeEnum.INPUTIO_EXCEPTION.getCode());
        }
        String originalFilename = file.getOriginalFilename();
        if(StringUtils.isEmpty(originalFilename)) {
            throw new RRException(MinioCodeEnum.UPLOAD_FILENAME_EMPTY.getMsg(), MinioCodeEnum.UPLOAD_FILENAME_EMPTY.getCode());
        }
        String prefix = UUID.randomUUID().toString();
        //获取后缀
        String fileSuffix = originalFilename.substring(originalFilename.lastIndexOf("."));
        String objectName = sdf.format(new Date())+prefix+fileSuffix;
        CompletableFuture.runAsync(() -> {
            try {
                // 上传文件流到minio服务器
                minioClient.putObject(
                        PutObjectArgs.builder().bucket(minioConfig.getBucket1()).object(objectName).stream(
                                        inputStream, file.getSize(), -1
                                )
                                .contentType(file.getContentType())
                                .build()
                );
            } catch (Exception e) {
                log.error(e.getMessage());
                throw new RRException(MinioCodeEnum.PUT_OBJECT_EXCEPTION.getMsg()+e.getMessage(), MinioCodeEnum.PUT_OBJECT_EXCEPTION.getCode());
            }
        }, executor);

        return minioConfig.getBucket1()+','+objectName;
    }

}
